//
//  DLRouteManager.swift
//  SwiftDemo
//
//  Created by ling on 2023/12/23.
//

import UIKit

class DWRouterManager {

    static let share : DWRouterManager = DWRouterManager.init()
    
    private var modules : [String : DWRouterModify] = [:]
    
    /// 缓存的映射
    private var cacheModules : [String : DWRouterModify] = [:]
    
    func regist<T:DWRouterModule>(_ moduleType : T.Type) {
        self.modules[moduleType.identifier] = DWRouterModify.init(identifier: moduleType.identifier, type: moduleType.self)
    }
    
    private init() {
        registAllModule()
    }
    
    func registAllModule() {
        reloadImageList()
    }
    
    private func reloadClassList(with image: UnsafePointer<CChar>) {
        var count : UInt32 = 0
        if let classNames = objc_copyClassNamesForImage(image, &count) {
            for i in 0..<Int(count) {
                if let type = objc_getClass(classNames[i]) as? DWRouterModule.Type {
                    self.regist(type)
                }
            }
        }
    }
    
    private func reloadImageList() {
        var count : UInt32 = 0
        let imageList = objc_copyImageNames(&count)
        let boundleName = ((Bundle.main.object(forInfoDictionaryKey: "CFBundleExecutable") as? String)?.replacingOccurrences(of: "-", with: "_") ?? "") + ".app/"
        for i in 0..<Int(count) {
            let image = imageList[i]
            let imageName : String = String(cString: image)
            if imageName.contains(boundleName) {
                self.reloadClassList(with: image)
            }
        }
    }
    
    /// 创建一个前往模块修改器
    /// - Parameter identifier: 前往模块的标识符
    /// - Returns: 模块修改器
    public func make(_ identifier:String) -> DWRouterModify? {
        if let modify = self.cacheModules[identifier] {
            return modify.copy()
        }
        for modify in self.modules.values {
            if identifier.hasPrefix(modify.identifier) {
                cacheModules[identifier] = modify
                return modify.copy()
            }
        }
        return nil
    }
    
}
